<?
/** @file
 * @author Andrzej Mararok Wasiak (mararok@gmail.com)
 */

require_once ('AutoLoader.php');

class ControllerException {
   private $Message;
   private $Code;
   private $User;
   
   function __construct($msg,$code, $user) {
      $this->Message = $msg;
      $this->Code = $code;
      $this->User = $user;
   }
   
   function toLog() {
      ControllerLogger::log(Logger::EXCEPTION, CONTROLLER_NAME.': '.$msg, $user);
   } 
   
   function getCode() {
      return $Code;
   } 
   
}

/** Base class for all controllers.
 */
abstract class Controller {
   const NO_ERROR = 'NO';
   const LOG_CONTROLLER_EXCEPTION = true;
   
   //! action to exec for controller.
   protected $Action;
   //! Parameters for action.
   protected $ActionParams;
   //! Action result, returned to client in json.
   protected $Result;
   
   //! Set true in child class if controller can processing request from not logged client.
   protected $AllowGuest = false;
   
   /** Executed for process the client action request.
    *  @code
    *    $controller = new ChildController();
    *    $controller->processRequest();
    *  @endcode
    */
   function processRequest() {
      try {
         $this->Result = new ActionResult();
         $result->add('error', self::NO_ERROR);
         $this->ActionParams = new ActionParams($_POST);
         
         $this->setUser();
         $this->setAction();
         $this->prepare();
         $this->processUserRequest();
      } catch (ControllerException $e) {
         if (LOG_CONTROLLER_EXCEPTION)
            $e->toLog();
         $this->Result->set('error',$e->getCode());
      }
   }

   private function setUser() {
      if ($this->AllowGuest) return;
      
      throw new ControllerException('no user from: '.$_SERVER['REMOTE_ADDR'],'noUser',-1);
   }
   
   private function setAction() {
      if (isset($_POST['action'])&&Action::isSupported($this, $_POST['action']))
         $this->Action = new Action($_POST['action']);
      else
         throw new ControllerException('bad request '.DB::safeString(implode(',',$_POST)).
                                       ' from: '.$_SERVER['REMOTE_ADDR'],
                                       'bad request',User::getID());
   }
   
   /** Here code that is called before the action.
    */
   protected function prepare() {}
   
   private function processUserRequest() {
      $this->execAction();
   }

   private function execAction() {
      try {
      $result = $this->Action->exec($this);
      } catch (ActionParamException $e) {
         throw new ControllerException($e->getMessage(),'invalidParam',User::getID());
      }
      $this->sendResponse();
   }
   
   private function sendResponse() {
      echo $this->Result;
   }
}
?>